package com.yhb.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yhb.channel.impl.ANYPAY.AnyPayChannel;
import com.yhb.model.Card;
import com.yhb.model.User;
import com.yhb.model.config.feeRate.FeeRateChannel;
import com.yhb.model.config.feeRate.FeeRateItem;
import com.yhb.model.config.feeRate.FeeRateRoot;
import lombok.extern.log4j.Log4j;
import lombok.var;
import me.edzh.spring.bootstrap.utils.JSONUtil;
import me.edzh.spring.bootstrap.utils.ResultCode;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Log4j
@Service
public class CommissionService {

    private volatile Map<String, FeeRateChannel> feeRates;

    public synchronized void updateRate(String yamlString) {
        var yaml = new Yaml();
        var res = yaml.loadAs(yamlString, Map.class);

        this.feeRates = JSONUtil.parseJson(res, new TypeReference<Map<String, FeeRateChannel>>() {});
        StringBuilder sb = new StringBuilder();

        for (String k : feeRates.keySet()) {
            sb.append(k).append("\n");
        }

        log.info("fee rate updated, channels:\n" + sb.toString());
    }

    public BigDecimal calcCommission(String channelType, User user, Card card, BigDecimal amount) {
        return amount.multiply(BigDecimal.ONE.subtract(commissionRate(channelType, user, card)));
    }

    public BigDecimal commissionRate(String channelType, User user, Card card) {
        var channel = this.feeRates.get(channelType);
        if (channel != null) {
            var rate = getFeeRate(card, channel);
            switch (user.getVipType()) {
                case PAYED:
                    return rate.getPAYED();
                case PRIME:
                    return rate.getPRIME();
                default:
                case ORDINARY:
                    return rate.getORDINARY();
            }

        }

        throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "commission unsettled for channel:" + channelType);
    }

    private FeeRateItem getFeeRate(Card card, FeeRateChannel channel) {
        if (channel.getSPECIAL() != null) {
            for (var special : channel.getSPECIAL()) {
                for (String bank : special.getBANKS()) {
                    if (card.getBankName().equals(bank)) {
                        return special.getRATES();
                    }
                }
            }
        }


        return channel.getCOMMON();
    }

    public static void main(String[] args) throws IOException {
        new CommissionService().updateRate(FileUtils.readFileToString(new File("/Users/edwardzhou/Documents/codes/yhb/new/api_server/deploy/runtime_dependencies/config/feeRate.yaml"), StandardCharsets.UTF_8));

    }
}
